use std::collections::HashMap;
use std::env;
use std::fs;
use syn::parse_file;

mod symboltable;
mod codechecker;
use symboltable::RustAnalyzer;

#[derive(Debug)]
enum Symbol {
    Crate { name: String },
    Module { name: String },
    Constant { name: String, ty: String },
    Static { name: String, ty: String },
    Macro { name: String, content: String },
    Struct { name: String, fields: SymbolTable },
    StructField { name: String, ty: String },
    Enum { name: String, variants: SymbolTable },
    EnumVariant {name: String, fields: SymbolTable},
    Union { name: String, fields: SymbolTable },
    Impl { type_name: String, methods: SymbolTable },
    Function { summary: FunctionSummary },
    Method { summary: FunctionSummary },
}

#[derive(Debug)]
struct FunctionSummary {
    name: String,
    is_unsafe: bool,
    inputs: Vec<(String, String)>,
    output: Option<String>,
}

#[derive(Debug)]
struct SymbolTable {
    symbols: HashMap<String, Symbol>,
}

impl SymbolTable {
    fn new() -> Self {
        SymbolTable {
            symbols: HashMap::new(),
        }
    }

    fn insert(&mut self, name: String, symbol: Symbol) {
        self.symbols.insert(name, symbol);
    }

    fn get(&self, name: &str) -> Option<&Symbol> {
        self.symbols.get(name)
    }
}

pub fn build_ast(file_path: &str) -> syn::File{
    // 读取 Rust 源码文件
    //let rust_code = fs::read_to_string(file_path).expect("Failed to read file");
    let rust_code = read_rust_file(file_path);

    //println!("{:?}", rust_code);
    // 解析 Rust 源码并生成 AST
    let error_info = format!("Failed to parse file:{}", file_path);
    let ast = parse_file(&rust_code).expect(&error_info);
    ast
}

pub fn read_rust_file(file_path:&str) -> String {
    let rust_code = fs::read_to_string(file_path).expect("Failed to read file");
    return rust_code;
}

fn main() {
    // Get the Rust filepath
    let args: Vec<String> = env::args().collect();

    // 3 parameters
    if args.len() != 3 {
        println!("Usage: {} <path_to_rust_file> <path_to_checked_rust_file>", args[0]);
        return;
    }

    // Rust file path
    let file_path = &args[1];

    let checked_rust_path = &args[2];

    let ast = build_ast(file_path);
    let context_code = read_rust_file(file_path);

    let mut analyzer = RustAnalyzer::new(context_code);
    analyzer.analyze(&ast);
    
    //println!("{}", analyzer.print_summary());

    let checked_code = read_rust_file(checked_rust_path);

    let (fixed_code, context_code, errors) = analyzer.check_and_fix_code(&checked_code);
    println!("{}", fixed_code);
    println!("---SPLIT---");
    println!("{}", context_code);
    //if !errors.is_empty() {
    //    println!("Error found:\n{}", errors.join("\n"));
    //}
    //match analyzer.check_and_fix_code(&checked_code) {
    //    Ok(fixed_code) => println!("Fixed code:\n{}", fixed_code),
    //    Err(errors) => println!("Errors found:\n{}", errors),
    //}
}
